package com.huaxin.device.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huaxin.device.dto.ResponseCode;
import com.huaxin.device.dto.ResponseResult;
import com.huaxin.device.dto.enums.EquipmentStatus;
import com.huaxin.device.dto.request.ElectricalEquipmentCreateReqDTO;
import com.huaxin.device.dto.request.ElectricalEquipmentPageListReqDTO;
import com.huaxin.device.dto.request.ElectricalEquipmentSetMaintenanceReqDTO;
import com.huaxin.device.dto.request.ElectricalEquipmentUpdateReqDTO;
import com.huaxin.device.dto.response.EquipmentStatsRespDTO;
import com.huaxin.device.mapper.ElectricalEquipmentMapper;
import com.huaxin.device.mapper.EquipmentCategoryMapper;
import com.huaxin.device.mapping.ElectricalEquipmentMapping;
import com.huaxin.device.models.ElectricalEquipment;
import com.huaxin.device.service.ElectricalEquipmentService;
import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.webjars.NotFoundException;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.springframework.util.StringUtils.hasText;

@Service
@RequiredArgsConstructor
public class ElectricalEquipmentServiceImpl extends ServiceImpl<ElectricalEquipmentMapper, ElectricalEquipment> implements ElectricalEquipmentService {

    private final ApplicationContext applicationContext;
    private final ElectricalEquipmentMapping mapping;
    private final ElectricalEquipmentMapper mapper;
    private final EquipmentCategoryMapper equipmentCategoryMapper;

    @Override
    public ResponseResult<ElectricalEquipment> create(ElectricalEquipmentCreateReqDTO in) {
        if (in == null) {
            return ResponseResult.parameterError(null, "参数错误");
        }

        // 校验 equipmentCode + familyId + orgId 是否已存在
        if (existsByFields(ElectricalEquipment::getEquipmentCode, in.getEquipmentCode(), in.getFamilyId(), in.getOrgId(), null)) {
            return ResponseResult.failure(ResponseCode.CUSTOM_BUSINESS_ERROR, "编号已存在", null);
        }
        // 校验 equipmentName + familyId + orgId 是否已存在
        if (existsByFields(ElectricalEquipment::getEquipmentName, in.getEquipmentName(), in.getFamilyId(), in.getOrgId(), null)) {
            return ResponseResult.failure(ResponseCode.CUSTOM_BUSINESS_ERROR, "名称已存在", null);
        }

        ElectricalEquipment entity = mapping.toEntity(in);
        entity.setStatus(EquipmentStatus.OFFLINE); // 默认添加时状态为离线
        if (!this.save(entity)) {
            return ResponseResult.failure(ResponseCode.INTERNAL_SERVER_ERROR, "添加失败，请稍后再试！", null);
        }
        return ResponseResult.ok(this.getById(entity.getId()));
    }

    @Override
    public ElectricalEquipment getByEquipmentId(String id) {
        if (!hasText(id)) {
            throw new IllegalArgumentException("设备ID不能为空");
        }
        ElectricalEquipment entity = this.getById(id);
        if (entity == null) {
            throw new NotFoundException("电力设备不存在");
        }
        return entity;
    }

    @Override
    public ResponseResult<String> update(ElectricalEquipmentUpdateReqDTO in) {
        if (in == null) {
            return ResponseResult.parameterError(null, "参数错误");
        }

        ElectricalEquipment entity = this.getByEquipmentId(in.getId());

        // 校验 equipmentCode + familyId + orgId 是否已存在(不包含当前ID)
        if (existsByFields(ElectricalEquipment::getEquipmentCode, in.getEquipmentCode(), in.getFamilyId(), in.getOrgId(), in.getId())) {
            return ResponseResult.failure(ResponseCode.CUSTOM_BUSINESS_ERROR, "编号已存在", null);
        }
        // 校验 equipmentName + familyId + orgId 是否已存在(不包含当前ID)
        if (existsByFields(ElectricalEquipment::getEquipmentName, in.getEquipmentName(), in.getFamilyId(), in.getOrgId(), in.getId())) {
            return ResponseResult.failure(ResponseCode.CUSTOM_BUSINESS_ERROR, "名称已存在", null);
        }

        mapping.updateEntity(in, entity);
        if (!this.updateById(entity)) {
            return ResponseResult.failure(ResponseCode.INTERNAL_SERVER_ERROR, "更新失败，请稍后再试！", null);
        }
        return ResponseResult.ok("更新成功");
    }

    @Override
    public ResponseResult<String> delete(String id) {
        ElectricalEquipment entity = this.getByEquipmentId(id);

        // 可以添加业务逻辑：如已启用设备不允许删除
        if (EquipmentStatus.NORMAL.equals(entity.getStatus())) {
            return ResponseResult.failure(ResponseCode.CUSTOM_BUSINESS_ERROR, "运行中的设备不允许删除", null);
        }

        boolean removed = this.applicationContext.getBean(ElectricalEquipmentService.class).removeById(id);
        if (!removed) {
            return ResponseResult.failure(ResponseCode.INTERNAL_SERVER_ERROR, "删除失败，请稍后重试", null);
        }
        return ResponseResult.ok("删除成功！");
    }

    @Override
    public ResponseResult<String> switchStatus(String id, EquipmentStatus status) {
        if (!hasText(id)) {
            return ResponseResult.parameterError(null, "设备ID不能为空");
        }

        // 查询设备是否存在
        ElectricalEquipment entity = this.getByEquipmentId(id);

        // 如果状态未变化，无需更新
        if (entity.getStatus().equals(status)) {
            return ResponseResult.parameterError(null, "设备状态已是 " + status.getDisplayName() + "，无需更改");
        }

        // 使用 LambdaUpdateWrapper 更新状态
        LambdaUpdateWrapper<ElectricalEquipment> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(ElectricalEquipment::getId, id)
                .set(ElectricalEquipment::getStatus, status);

        boolean updated = this.update(wrapper);
        if (!updated) {
            return ResponseResult.failure(ResponseCode.INTERNAL_SERVER_ERROR, "设备状态切换失败，请重试", null);
        }
        return ResponseResult.ok("设备状态切换成功");
    }

    @Override
    public ResponseResult<IPage<ElectricalEquipment>> pageQuery(ElectricalEquipmentPageListReqDTO in) {
        if (in == null) {
            return ResponseResult.parameterError(null, "参数错误");
        }

        IPage<ElectricalEquipment> page = new Page<>(in.getPageNum(), in.getPageSize());
        LambdaQueryWrapper<ElectricalEquipment> wrapper = new LambdaQueryWrapper<>();

        if (hasText(in.getEquipmentName())) {
            wrapper.like(ElectricalEquipment::getEquipmentName, in.getEquipmentName());
        }
        if (hasText(in.getEquipmentCode())) {
            wrapper.eq(ElectricalEquipment::getEquipmentCode, in.getEquipmentCode());
        }
        if (hasText(in.getModelId())) {
            wrapper.eq(ElectricalEquipment::getModelId, in.getModelId());
        }
        if (hasText(in.getCategoryId())) {
            wrapper.eq(ElectricalEquipment::getCategoryId, in.getCategoryId());
        }
        if (in.getStatus() != null) {
            wrapper.eq(ElectricalEquipment::getStatus, in.getStatus());
        }
        if (hasText(in.getRoomId())) {
            wrapper.eq(ElectricalEquipment::getRoomId, in.getRoomId());
        }
        if (hasText(in.getWellId())) {
            wrapper.eq(ElectricalEquipment::getWellId, in.getWellId());
        }
        if (hasText(in.getCabinetId())) {
            wrapper.eq(ElectricalEquipment::getCabinetId, in.getCabinetId());
        }
        if (in.getInstallDateStart() != null) {
            wrapper.ge(ElectricalEquipment::getInstallDate, in.getInstallDateStart());
        }
        if (in.getInstallDateEnd() != null) {
            wrapper.le(ElectricalEquipment::getInstallDate, in.getInstallDateEnd());
        }
        if (hasText(in.getOrgId())) {
            wrapper.eq(ElectricalEquipment::getOrgId, in.getOrgId());
        }
        if (hasText(in.getFamilyId())) {
            wrapper.eq(ElectricalEquipment::getFamilyId, in.getFamilyId());
        }

        wrapper.orderByDesc(ElectricalEquipment::getCreatedAt);
        IPage<ElectricalEquipment> resultPage = this.page(page, wrapper);
        return ResponseResult.ok(resultPage);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult<String> batchSetMaintenance(@RequestBody ElectricalEquipmentSetMaintenanceReqDTO in) {
        if (in == null) {
            return ResponseResult.parameterError(null, "参数错误");
        }
        if (in.getEquipmentIds() == null) {
            return ResponseResult.parameterError(null, "参数错误");
        }

        List<ElectricalEquipment> list = in.getEquipmentIds().stream()
                .map(id -> {
                    ElectricalEquipment eq = new ElectricalEquipment();
                    eq.setId(id);
                    eq.setLastMaintenanceDate(in.getLastMaintenanceDate());
                    eq.setNextMaintenanceDate(in.getNextMaintenanceDate());
                    return eq;
                })
                .collect(Collectors.toList());
        boolean updated = this.updateBatchById(list);
        if (!updated) {
            return ResponseResult.failure(ResponseCode.INTERNAL_SERVER_ERROR, "批量设置维保信息失败，请稍后重试", null);
        }
        return ResponseResult.ok("批量设置维保信息成功");
    }

    @Override
    public List<ElectricalEquipment> listByModelId(String modelId) {
        return lambdaQuery()
                .eq(ElectricalEquipment::getModelId, modelId)
                .orderByAsc(ElectricalEquipment::getCreatedAt)
                .list();
    }

    @Override
    public List<ElectricalEquipment> listByCategoryId(String categoryId) {
        return lambdaQuery()
                .eq(ElectricalEquipment::getCategoryId, categoryId)
                .orderByAsc(ElectricalEquipment::getCreatedAt)
                .list();
    }

    @Override
    public List<ElectricalEquipment> listByRoomId(String roomId) {
        return lambdaQuery()
                .eq(ElectricalEquipment::getRoomId, roomId)
                .orderByAsc(ElectricalEquipment::getCreatedAt)
                .list();
    }

    @Override
    public List<ElectricalEquipment> listByWellId(String wellId) {
        return lambdaQuery()
                .eq(ElectricalEquipment::getWellId, wellId)
                .orderByAsc(ElectricalEquipment::getCreatedAt)
                .list();
    }

    @Override
    public List<ElectricalEquipment> listByCabinetId(String cabinetId) {
        return lambdaQuery()
                .eq(ElectricalEquipment::getCabinetId, cabinetId)
                .orderByAsc(ElectricalEquipment::getCreatedAt)
                .list();
    }

    @Override
    public ResponseResult<EquipmentStatsRespDTO> getStats() {
        EquipmentStatsRespDTO stats = new EquipmentStatsRespDTO();
        EquipmentStatsRespDTO.StatusCount statusCount = new EquipmentStatsRespDTO.StatusCount();

        // 1. 总设备数
        LambdaQueryWrapper<ElectricalEquipment> totalWrapper = new LambdaQueryWrapper<>();
        stats.setTotal(count(totalWrapper));

        // 2. 按运行状态统计
        List<Map<String, Object>> statusList = this.listMaps(
                new QueryWrapper<ElectricalEquipment>()
                        .select("status, COUNT(*) AS count")
                        .eq("is_deleted", 0)
                        .groupBy("status")
        );

        for (Map<String, Object> map : statusList) {
            String status = (String) map.get("status"); // 假设 status 存储为字符串
            Long count = (Long) map.get("count");

            switch (status) {
                case "normal":
                    statusCount.setNormal(count.intValue());
                    break;
                case "fault":
                    statusCount.setFault(count.intValue());
                    break;
                case "maintenance":
                    statusCount.setMaintenance(count.intValue());
                    break;
                case "repair":
                    statusCount.setRepair(count.intValue());
                    break;
                case "offline":
                    statusCount.setOffline(count.intValue());
                    break;
            }
        }

        // 3. 即将到期维保（7天内）
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime dueEnd = now.plusDays(7);
        int dueCount = Math.toIntExact(lambdaQuery()
                .isNotNull(ElectricalEquipment::getNextMaintenanceDate)
                .ge(ElectricalEquipment::getNextMaintenanceDate, now)
                .le(ElectricalEquipment::getNextMaintenanceDate, dueEnd)
                .count());
        stats.setMaintenanceDueCount(dueCount);

        // 4. 按分类统计设备数量（核心：JOIN 查询）
        List<EquipmentStatsRespDTO.CategoryCount> byCategory = equipmentCategoryMapper.selectEquipmentCountByCategory();
        stats.setByCategory(byCategory);

        return ResponseResult.ok(stats);
    }

    /**
     * 检查多个字段值组合是否已存在（排除当前ID）
     *
     * @param fieldGetter 字段Getter
     * @param fieldValue  字段值
     * @param familyId    家庭ID
     * @param orgId       组织ID
     * @param excludeId   要排除的ID（可为null）
     * @return 是否存在匹配记录
     */
    private boolean existsByFields(
            SFunction<ElectricalEquipment, ?> fieldGetter,
            Object fieldValue,
            String familyId,
            String orgId,
            String excludeId) {

        if (fieldGetter == null) return false;

        LambdaQueryWrapper<ElectricalEquipment> wrapper = new LambdaQueryWrapper<>();

        if (fieldValue == null ||
                (fieldValue instanceof CharSequence cs && cs.toString().trim().isEmpty())) {
            wrapper.and(wrapper1 -> wrapper1
                    .isNull(fieldGetter)
                    .or().eq(fieldGetter, "")
            );
        } else {
            wrapper.eq(fieldGetter, fieldValue.toString().trim());
        }

        if (familyId == null || familyId.trim().isEmpty()) {
            wrapper.and(wrapper1 -> wrapper1
                    .isNull(ElectricalEquipment::getFamilyId)
                    .or().eq(ElectricalEquipment::getFamilyId, "")
            );
        } else {
            wrapper.eq(ElectricalEquipment::getFamilyId, familyId.trim());
        }

        if (orgId == null || orgId.trim().isEmpty()) {
            wrapper.and(wrapper1 -> wrapper1
                    .isNull(ElectricalEquipment::getOrgId)
                    .or().eq(ElectricalEquipment::getOrgId, "")
            );
        } else {
            wrapper.eq(ElectricalEquipment::getOrgId, orgId.trim());
        }

        if (excludeId != null && !excludeId.trim().isEmpty()) {
            wrapper.ne(ElectricalEquipment::getId, excludeId.trim());
        }

        return this.count(wrapper) > 0;
    }
}